package model;

import static util.Constants.FILE_BAG;
import static util.Strings.STR_BAG_FILE_NOT_FOUND;
import static util.Strings.STR_EMPTY_BAG;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.StringTokenizer;

import exceptions.EmptyBagException;

/**
 * Cette classe représente le sac des tuiles dans lequel les joueurs piochent
 * leurs lettres. Il est chargé à partir d'un fichier texte.
 * 
 * @author Lucile Gramusset et Guillaume Poussel
 * 
 */
public class Bag {

    /**
     * Contenu du sac
     */
    private ArrayList<Tile> content = new ArrayList<Tile>();

    /**
     * Construit le sac à partir de la distribution donnée dans le fichier
     * texte.
     */
    public Bag() {
        BufferedReader bagText;
        String line = "";
        // Ouvrir le fichier du sac
        try {
            bagText = new BufferedReader(new FileReader(FILE_BAG));
            if (bagText == null) {
                throw new FileNotFoundException(String.format(
                        STR_BAG_FILE_NOT_FOUND, FILE_BAG));
            }

            // Remplit le sac

            while ((line = bagText.readLine()) != null) {
                if (line != null) {
                    StringTokenizer st = new StringTokenizer(line);

                    while (st.hasMoreTokens()) {
                        String strLetter = st.nextToken().toUpperCase();
                        if (st.hasMoreTokens()) {
                            int count = 0;
                            int score = 0;
                            if (st.hasMoreTokens()) {
                                count = Integer.parseInt(st.nextToken());
                            }
                            if (st.hasMoreTokens()) {
                                score = Integer.parseInt(st.nextToken());
                            }
                            while (count-- > 0) {
                                content.add(new Tile(Letter.valueOf(strLetter),
                                        score));
                            }
                        }
                    }
                }
            }
            while (line != null);

            bagText.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Détermine si le sac est vide ou non
     * 
     * @return <code>true</code> si le sac est vide, <code>false</code> sinon.
     */
    public boolean isEmpty() {
        return content.isEmpty();
    }

    /**
     * Donne la taille du sac en nombre de tuiles restantes
     * 
     * @return Le nombre de tuiles restantes
     */
    public int size() {
        return content.size();
    }

    /**
     * Retourne une tuile au hasard dans le sac. Cette méthode mélange le sac à
     * chaque fois que l'on pioche une tuile.
     * 
     * @return Une tuile piochée au hasard dans le sac
     * @throws EmptyBagException
     *             Si le sac est vide, une exception est levée
     */
    public Tile take() throws EmptyBagException {
        if (isEmpty())
            throw new EmptyBagException(STR_EMPTY_BAG);
        Collections.shuffle(content);
        return content.remove(content.size() - 1);
    }

    /**
     * Repose une tuile dans le sac et mélange le sac.
     * 
     * @param tile
     *            La tuile à reposer dans le sac
     */
    public void put(Tile tile) {
        content.add(tile);
        Collections.shuffle(content);
    }

    public String toString() {
        return content.toString();
    }
}
